package com.serial.comm.config.rabbitmq;

import com.serial.comm.core.constants.RabbitConst;
import org.springframework.amqp.core.*;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.Map;

/**
 * MQ 配置类
 */
@Configuration
public class RabbitMQConfig {


    /******************************************交换机******************************************
     * 声明业务Exchange
     */
    @Bean("serialExchange")
    public DirectExchange businessExchange() {
        return new DirectExchange(RabbitConst.BUSINESS_EXCHANGE);
    }


    /**
     * 声明死信Exchange
     */
    @Bean("deadLetterExchange")
    public DirectExchange deadLetterExchange() {
        return new DirectExchange(RabbitConst.DEAD_LETTER_EXCHANGE);
    }

    /**
     * 声明重试Exchange
     */
    @Bean("serialRetryExchange")
    public DirectExchange businessRetryExchange() {
        return new DirectExchange(RabbitConst.BUSINESS_EXCHANGE_RETRY);
    }

    /**
     * 声明重试死信Exchange
     */
    @Bean("deadLetterRetryExchange")
    public DirectExchange deadLetterRetryExchange() {
        return new DirectExchange(RabbitConst.DEAD_LETTER_EXCHANGE_RETRY);
    }


    /******************************************队列******************************************
     * 声明 串口读取 原始电报 业务队列
     *
     * @return
     */
    @Bean("serialBaseReadQueue")
    public Queue serialBaseReadQueue() {
        Map<String, Object> args = new HashMap<>(2);
//       x-dead-letter-exchange    这里声明当前队列绑定的死信交换机
        args.put("x-dead-letter-exchange", RabbitConst.DEAD_LETTER_EXCHANGE);
//       x-dead-letter-routing-key  这里声明当前队列的死信路由key
        args.put("x-dead-letter-routing-key", RabbitConst.QUEUE_ROUTING_KEY_BASE_READ);
        return QueueBuilder.durable(RabbitConst.BUSINESS_QUEUE_BASE_READ).withArguments(args).build();
    }

    /**
     * 声明 串口读取 单一电报 业务队列
     *
     * @return
     */
    @Bean("serialUnitaryReadQueue")
    public Queue serialUnitaryReadQueue() {
        Map<String, Object> args = new HashMap<>(2);
//       x-dead-letter-exchange    这里声明当前队列绑定的死信交换机
        args.put("x-dead-letter-exchange", RabbitConst.DEAD_LETTER_EXCHANGE);
//       x-dead-letter-routing-key  这里声明当前队列的死信路由key
        args.put("x-dead-letter-routing-key", RabbitConst.QUEUE_ROUTING_KEY_UNITARY_READ);
        return QueueBuilder.durable(RabbitConst.BUSINESS_QUEUE_UNITARY_READ).withArguments(args).build();
    }

    /**
     * 声明串口写入业务队列
     *
     * @return
     */
    @Bean("serialWriteQueue")
    public Queue serialWriteQueue() {
        Map<String, Object> args = new HashMap<>(2);
        args.put("x-dead-letter-exchange", RabbitConst.DEAD_LETTER_EXCHANGE);
        args.put("x-dead-letter-routing-key", RabbitConst.QUEUE_ROUTING_KEY_WRITE);
        return QueueBuilder.durable(RabbitConst.BUSINESS_QUEUE_WRITE).withArguments(args).build();
    }

    /**
     * 声明 串口写入重试 队列
     *
     * @return
     */
    @Bean("serialWriteRetryQueue")
    public Queue serialWriteRetryQueue() {
        Map<String, Object> args = new HashMap<>();
        args.put("x-dead-letter-exchange", RabbitConst.DEAD_LETTER_EXCHANGE_RETRY);
        args.put("x-dead-letter-routing-key", RabbitConst.QUEUE_ROUTING_KEY_WRITE_RETRY);
        //消息 5s 过期
        args.put("x-message-ttl", 5000L);
        return QueueBuilder.durable(RabbitConst.BUSINESS_QUEUE_WRITE_RETRY).withArguments(args).build();
    }

    /**
     * 声明 串口读取 原始电报 死信队列
     *
     * @return
     */
    @Bean("serialDeadLetterBaseReadQueue")
    public Queue serialDeadLetterQueue() {
        return new Queue(RabbitConst.DEAD_LETTER_QUEUE_BASE_READ);
    }

    /**
     * 声明 串口读取 单一电报 死信队列
     *
     * @return
     */
    @Bean("serialDeadLetterUnitaryReadQueue")
    public Queue serialDeadUnitaryLetterQueue() {
        return new Queue(RabbitConst.DEAD_LETTER_QUEUE_UNITARY_READ);
    }


    /**
     * 声明 串口写入 死信队列
     *
     * @return
     */
    @Bean("serialDeadLetterWriteQueue")
    public Queue serialDeadLetterWriteQueue() {
        return new Queue(RabbitConst.DEAD_LETTER_QUEUE_WRITE);
    }

    /**
     * 声明 串口重试 死信队列
     *
     * @return
     */
    @Bean("serialDeadLetterWriteRetryQueue")
    public Queue serialDeadLetterWriteRetryQueue() {
        return new Queue(RabbitConst.DEAD_LETTER_QUEUE_WRITE_RETRY);
    }


    /******************************************关系******************************************
     * 声明 串口读取 原始电报 业务队列 绑定关系
     *
     * @param queue
     * @param exchange
     * @return
     */
    @Bean
    public Binding serialBaseReadBinding(@Qualifier("serialBaseReadQueue") Queue queue,
                                         @Qualifier("serialExchange") DirectExchange exchange) {
        return BindingBuilder.bind(queue).to(exchange).with(RabbitConst.QUEUE_ROUTING_KEY_BASE_READ);
    }

    /**
     * 声明 串口读取 单一电报 读取业务队列 绑定关系
     *
     * @param queue
     * @param exchange
     * @return
     */
    @Bean
    public Binding serialUnitaryReadBinding(@Qualifier("serialUnitaryReadQueue") Queue queue,
                                            @Qualifier("serialExchange") DirectExchange exchange) {
        return BindingBuilder.bind(queue).to(exchange).with(RabbitConst.QUEUE_ROUTING_KEY_UNITARY_READ);
    }

    /**
     * 声明串口写入业务队列 绑定关系
     *
     * @param queue
     * @param exchange
     * @return
     */
    @Bean
    public Binding serialWriteBinding(@Qualifier("serialWriteQueue") Queue queue,
                                      @Qualifier("serialExchange") DirectExchange exchange) {
        return BindingBuilder.bind(queue).to(exchange).with(RabbitConst.QUEUE_ROUTING_KEY_WRITE);
    }

    /**
     * 声明串口写入重试队列 绑定关系
     *
     * @param queue
     * @param exchange
     * @return
     */
    @Bean
    public Binding serialWriteRetryBinding(@Qualifier("serialWriteRetryQueue") Queue queue,
                                           @Qualifier("serialRetryExchange") DirectExchange exchange) {
        return BindingBuilder.bind(queue).to(exchange).with(RabbitConst.QUEUE_ROUTING_KEY_WRITE_RETRY);
    }

    /**
     * 声明 串口读取 死信队列绑定关系
     *
     * @param queue
     * @param exchange
     * @return
     */
    @Bean
    public Binding deadLetterBaseReadBinding(@Qualifier("serialDeadLetterBaseReadQueue") Queue queue,
                                             @Qualifier("deadLetterExchange") DirectExchange exchange) {
        return BindingBuilder.bind(queue).to(exchange).with(RabbitConst.QUEUE_ROUTING_KEY_BASE_READ);
    }

    /**
     * 声明 串口读取单一电报 死信队列绑定关系
     *
     * @param queue
     * @param exchange
     * @return
     */
    @Bean
    public Binding deadLetterUnitaryReadBinding(@Qualifier("serialDeadLetterUnitaryReadQueue") Queue queue,
                                                @Qualifier("deadLetterExchange") DirectExchange exchange) {
        return BindingBuilder.bind(queue).to(exchange).with(RabbitConst.QUEUE_ROUTING_KEY_UNITARY_READ);
    }


    /**
     * 声明 串口写入 死信队列绑定关系
     *
     * @param queue
     * @param exchange
     * @return
     */
    @Bean
    public Binding deadLetterWriteBinding(@Qualifier("serialDeadLetterWriteQueue") Queue queue,
                                          @Qualifier("deadLetterExchange") DirectExchange exchange) {
        return BindingBuilder.bind(queue).to(exchange).with(RabbitConst.QUEUE_ROUTING_KEY_WRITE);
    }

    /**
     * 声明 串口写入重试 死信队列绑定关系
     *
     * @param queue
     * @param exchange
     * @return
     */
    @Bean
    public Binding deadLetterWriteRetryBinding(@Qualifier("serialDeadLetterWriteRetryQueue") Queue queue,
                                               @Qualifier("deadLetterRetryExchange") DirectExchange exchange) {
        return BindingBuilder.bind(queue).to(exchange).with(RabbitConst.QUEUE_ROUTING_KEY_WRITE_RETRY);
    }

    @Bean("fodbReadQueue")
    public Queue fodbReadQueue() {
        return new Queue(RabbitConst.QUEUE_FODB_READ);
    }


    @Bean("fodbWriteQueue")
    public Queue fodbWriteQueue() {
        return new Queue(RabbitConst.QUEUE_FODB_WRITE);
    }
}
